<template>
  <div class="chart-container">
    <div class="chart-header">
      <h3>产品销售预测对比</h3>
      <el-select v-model="displayMode" size="small" class="display-selector">
        <el-option label="排行显示" value="rank" />
        <el-option label="对比显示" value="compare" />
      </el-select>
    </div>
    
    <div class="chart-content" :class="{ 'is-loading': loading }">
      <div ref="chartRef" class="echarts-wrapper"></div>
      <div v-if="loading" class="loading-overlay">
        <el-skeleton animated :rows="5" />
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, shallowRef, onMounted, onUnmounted, watch } from 'vue';
import * as echarts from 'echarts/core';
import { BarChart } from 'echarts/charts';
import {
  TitleComponent,
  TooltipComponent,
  GridComponent,
  LegendComponent
} from 'echarts/components';
import { CanvasRenderer } from 'echarts/renderers';

// 注册必要的组件
echarts.use([
  TitleComponent,
  TooltipComponent,
  GridComponent,
  LegendComponent,
  BarChart,
  CanvasRenderer
]);

const props = defineProps({
  productData: {
    type: Array,
    default: () => []
  },
  loading: {
    type: Boolean,
    default: false
  }
});

const chartRef = ref(null);
const chart = shallowRef(null);
const displayMode = ref('rank'); // 'rank' 或 'compare'
let resizeObserver = null;

// 监听数据变化，更新图表
watch([() => props.productData, displayMode], () => {
  if (chart.value && props.productData?.length > 0) {
    updateChart();
  }
}, { deep: true });

// 监听加载状态
watch(() => props.loading, (newVal) => {
  if (!newVal && chart.value) {
    updateChart();
  }
});

onMounted(() => {
  if (chartRef.value) {
    initChart();
    
    // 监听窗口大小变化，添加节流函数以避免频繁触发
    const resizeHandler = () => {
      if (chart.value) {
        chart.value.resize();
      }
    };
    
    // 使用防抖函数处理resize事件
    const debouncedResize = debounce(resizeHandler, 100);
    
    resizeObserver = new ResizeObserver(() => {
      debouncedResize();
    });
    resizeObserver.observe(chartRef.value);
  }
});

onUnmounted(() => {
  // 销毁图表实例
  if (chart.value) {
    chart.value.dispose();
    chart.value = null;
  }
  
  // 清除resize观察者
  if (resizeObserver) {
    resizeObserver.disconnect();
    resizeObserver = null;
  }
});

// 初始化图表
function initChart() {
  if (!chartRef.value) return;
  
  // 确保图表容器有固定高度
  const container = chartRef.value;
  if (!container.style.height || container.style.height === 'auto') {
    container.style.height = '400px';
  }
  
  chart.value = echarts.init(chartRef.value);
  updateChart();
}

// 更新图表数据
function updateChart() {
  if (!chart.value || props.loading) return;
  
  if (displayMode.value === 'rank') {
    renderRankChart();
  } else {
    renderCompareChart();
  }
}

// 渲染排行显示图表
function renderRankChart() {
  // 准备数据 - 按实际销售额排序
  const sortedData = [...props.productData].sort((a, b) => b.actual_amount - a.actual_amount);
  const productNames = sortedData.map(item => item.product_name);
  const actualAmounts = sortedData.map(item => item.actual_amount);
  const predictedAmounts = sortedData.map(item => item.predicted_amount);
  
  // 计算增长率
  const growthRates = sortedData.map(item => {
    const growth = ((item.predicted_amount - item.actual_amount) / item.actual_amount) * 100;
    return growth.toFixed(1);
  });
  
  // 设置图表选项
  const option = {
    backgroundColor: 'transparent',
    tooltip: {
      trigger: 'axis',
      backgroundColor: 'rgba(19, 20, 42, 0.9)',
      borderColor: 'rgba(42, 42, 87, 0.8)',
      textStyle: {
        color: '#e0e0ff'
      },
      formatter: function(params) {
        const productName = params[0].name;
        const actual = params[0].value.toLocaleString('zh-CN', {
          minimumFractionDigits: 2,
          maximumFractionDigits: 2
        });
        const predicted = params[1].value.toLocaleString('zh-CN', {
          minimumFractionDigits: 2,
          maximumFractionDigits: 2
        });
        const growth = growthRates[params[0].dataIndex];
        
        return `
          <div style="padding: 5px">
            <div style="font-weight: bold; margin-bottom: 8px">${productName}</div>
            <div style="display: flex; justify-content: space-between; margin-bottom: 5px">
              <span>实际销售额:</span>
              <span style="font-weight: 600">¥${actual}</span>
            </div>
            <div style="display: flex; justify-content: space-between; margin-bottom: 5px">
              <span>预测销售额:</span>
              <span style="font-weight: 600">¥${predicted}</span>
            </div>
            <div style="display: flex; justify-content: space-between; margin-top: 5px; color: ${parseFloat(growth) > 0 ? '#00ffb3' : '#ff5e7b'}">
              <span>预计增长率:</span>
              <span style="font-weight: 600">${growth}%</span>
            </div>
          </div>
        `;
      }
    },
    legend: {
      data: ['实际销售额', '预测销售额'],
      textStyle: {
        color: '#7171a6'
      },
      right: '4%',
      top: '0%'
    },
    grid: {
      left: '3%',
      right: '4%',
      bottom: '15%',
      top: '15%',
      containLabel: true
    },
    xAxis: {
      type: 'value',
      axisLine: {
        show: false
      },
      axisLabel: {
        color: '#7171a6',
        formatter: function(value) {
          if (value >= 1000000) {
            return (value / 1000000).toFixed(1) + 'M';
          } else if (value >= 1000) {
            return (value / 1000).toFixed(0) + 'K';
          }
          return value;
        }
      },
      splitLine: {
        lineStyle: {
          color: 'rgba(113, 113, 166, 0.1)'
        }
      }
    },
    yAxis: {
      type: 'category',
      data: productNames,
      axisLine: {
        lineStyle: {
          color: 'rgba(113, 113, 166, 0.3)'
        }
      },
      axisLabel: {
        color: '#e0e0ff',
        formatter: function(value) {
          // 产品名称可能很长，需要截断
          if (value.length > 10) {
            return value.substring(0, 10) + '...';
          }
          return value;
        }
      },
      axisTick: {
        alignWithLabel: true,
        lineStyle: {
          color: 'rgba(113, 113, 166, 0.3)'
        }
      }
    },
    series: [
      {
        name: '实际销售额',
        type: 'bar',
        data: actualAmounts,
        barWidth: '40%',
        barGap: '0%',
        itemStyle: {
          color: {
            type: 'linear',
            x: 1,
            y: 0,
            x2: 0,
            y2: 0,
            colorStops: [
              { offset: 0, color: '#3a36db' },
              { offset: 1, color: '#00c9ff' }
            ]
          },
          borderRadius: [0, 4, 4, 0]
        },
        label: {
          show: true,
          position: 'right',
          formatter: function(params) {
            return '¥' + params.value.toLocaleString('zh-CN', {
              minimumFractionDigits: 0,
              maximumFractionDigits: 0
            });
          },
          textStyle: {
            color: '#7171a6',
            fontSize: 12
          }
        }
      },
      {
        name: '预测销售额',
        type: 'bar',
        data: predictedAmounts,
        barWidth: '40%',
        barGap: '0%',
        itemStyle: {
          color: {
            type: 'linear',
            x: 1,
            y: 0,
            x2: 0,
            y2: 0,
            colorStops: [
              { offset: 0, color: '#00e1d9' },
              { offset: 1, color: '#00ffb3' }
            ]
          },
          borderRadius: [0, 4, 4, 0]
        },
        label: {
          show: true,
          position: 'right',
          formatter: function(params) {
            const index = params.dataIndex;
            const growth = growthRates[index];
            return `¥${params.value.toLocaleString('zh-CN', {
              minimumFractionDigits: 0,
              maximumFractionDigits: 0
            })} (${growth}%)`;
          },
          textStyle: {
            color: '#00ffb3',
            fontSize: 12
          }
        }
      }
    ]
  };
  
  chart.value.setOption(option, true);
}

// 渲染对比显示图表
function renderCompareChart() {
  // 准备数据
  const productNames = props.productData.map(item => item.product_name);
  
  // 构建对比数据
  const compareData = props.productData.map(item => {
    const growth = ((item.predicted_amount - item.actual_amount) / item.actual_amount) * 100;
    return {
      product: item.product_name,
      actual: item.actual_amount,
      predicted: item.predicted_amount,
      growth: growth.toFixed(1)
    };
  });
  
  // 设置图表选项
  const option = {
    backgroundColor: 'transparent',
    tooltip: {
      trigger: 'item',
      backgroundColor: 'rgba(19, 20, 42, 0.9)',
      borderColor: 'rgba(42, 42, 87, 0.8)',
      textStyle: {
        color: '#e0e0ff'
      },
      formatter: function(params) {
        const data = compareData[params.dataIndex];
        
        return `
          <div style="padding: 5px">
            <div style="font-weight: bold; margin-bottom: 8px">${data.product}</div>
            <div style="display: flex; justify-content: space-between; margin-bottom: 5px">
              <span>实际销售额:</span>
              <span style="font-weight: 600">¥${data.actual.toLocaleString('zh-CN', {
                minimumFractionDigits: 2,
                maximumFractionDigits: 2
              })}</span>
            </div>
            <div style="display: flex; justify-content: space-between; margin-bottom: 5px">
              <span>预测销售额:</span>
              <span style="font-weight: 600">¥${data.predicted.toLocaleString('zh-CN', {
                minimumFractionDigits: 2,
                maximumFractionDigits: 2
              })}</span>
            </div>
            <div style="display: flex; justify-content: space-between; margin-top: 5px; color: ${parseFloat(data.growth) > 0 ? '#00ffb3' : '#ff5e7b'}">
              <span>预计增长率:</span>
              <span style="font-weight: 600">${data.growth}%</span>
            </div>
          </div>
        `;
      }
    },
    grid: {
      left: '3%',
      right: '4%',
      bottom: '15%',
      top: '10%',
      containLabel: true
    },
    xAxis: {
      type: 'category',
      data: productNames,
      axisLine: {
        lineStyle: {
          color: 'rgba(113, 113, 166, 0.3)'
        }
      },
      axisLabel: {
        color: '#7171a6',
        interval: 0,
        rotate: 30,
        formatter: function(value) {
          // 产品名称可能很长，需要截断
          if (value.length > 8) {
            return value.substring(0, 8) + '...';
          }
          return value;
        }
      },
      axisTick: {
        alignWithLabel: true,
        lineStyle: {
          color: 'rgba(113, 113, 166, 0.3)'
        }
      }
    },
    yAxis: {
      type: 'value',
      axisLine: {
        show: false
      },
      axisLabel: {
        color: '#7171a6',
        formatter: function(value) {
          if (value >= 1000000) {
            return (value / 1000000).toFixed(1) + 'M';
          } else if (value >= 1000) {
            return (value / 1000).toFixed(0) + 'K';
          }
          return value;
        }
      },
      splitLine: {
        lineStyle: {
          color: 'rgba(113, 113, 166, 0.1)'
        }
      }
    },
    series: compareData.map((item, index) => {
      const growth = parseFloat(item.growth);
      const color = growth > 0 ? '#00ffb3' : '#ff5e7b';
      
      return {
        type: 'bar',
        name: item.product,
        data: Array(productNames.length).fill(0).map((_, i) => i === index ? item.predicted : 0),
        barWidth: '50%',
        stack: 'total',
        emphasis: {
          focus: 'self'
        },
        itemStyle: {
          color: {
            type: 'linear',
            x: 0,
            y: 0,
            x2: 0,
            y2: 1,
            colorStops: [
              { offset: 0, color: growth > 0 ? '#00e1d9' : '#ff7a9c' },
              { offset: 1, color: growth > 0 ? '#00ffb3' : '#ff5e7b' }
            ]
          },
          borderRadius: [4, 4, 0, 0]
        },
        backgroundStyle: {
          color: 'rgba(113, 113, 166, 0.1)'
        },
        showBackground: true,
        label: {
          show: true,
          position: 'top',
          formatter: function() {
            return `${growth > 0 ? '+' : ''}${growth}%`;
          },
          textStyle: {
            color: color,
            fontSize: 12,
            fontWeight: 'bold'
          }
        }
      };
    })
  };
  
  chart.value.setOption(option, true);
}

// 防抖函数
function debounce(fn, delay) {
  let timer = null;
  return function() {
    const context = this;
    const args = arguments;
    if (timer) {
      clearTimeout(timer);
    }
    timer = setTimeout(() => {
      fn.apply(context, args);
    }, delay);
  };
}
</script>

<style scoped>
.chart-container {
  background-color: var(--bg-card, #13142a);
  border-radius: 8px;
  border: 1px solid var(--border-color, #2a2a57);
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
  overflow: hidden;
  height: 100%;
  display: flex;
  flex-direction: column;
}

.chart-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px 20px;
  border-bottom: 1px solid var(--border-color, #2a2a57);
}

.chart-header h3 {
  margin: 0;
  font-size: 16px;
  font-weight: 600;
  color: var(--text-primary, #e0e0ff);
}

.display-selector {
  width: 120px;
}

.chart-content {
  flex: 1;
  position: relative;
  min-height: 0;
  height: 100%;
  display: flex;
  flex-direction: column;
}

.chart-content.is-loading {
  opacity: 0.7;
}

.echarts-wrapper {
  width: 100%;
  flex: 1;
  min-height: 0;
  height: 100%;
}

.loading-overlay {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(19, 20, 42, 0.7);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 10;
  padding: 20px;
}
</style> 